﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Data;
using PanGu;

namespace PatientInformationExtract.MainInterface.Models.XMLCS
{
    class EventLogXMLParser
    {
        private XmlDocument _eventLogXml;
        public XmlDocument EventLogXml { get { return this._eventLogXml; } }
        private string _eventLogFilePath;
        public string EventLogFilePath { get { return this._eventLogFilePath; } }
        private XmlDocument _encodingDictionaryXml;
        public XmlDocument EncodingDictionaryXml { get { return this._encodingDictionaryXml; } }
        private string _encodingDictionaryFilePath;
        public string EncodingDictionaryFilePath { get { return this._encodingDictionaryFilePath; } }
        private XmlNodeList _patientNodes;
        private DataTable _observationDataTable;
        public DataTable ObservationDataTable { get { return this._observationDataTable; } }
        private DataTable _medicalInterventionDataTable;
        public DataTable MedicalInterventionDataTable { get { return this._medicalInterventionDataTable; } }
        private Dictionary<string, string> _encodingDictionary;
        private bool _isEncoded;
        public bool IsEncoded { get { return this._isEncoded; } }

        public EventLogXMLParser()
        {
            _observationDataTable = new System.Data.DataTable("Observation");
            _observationDataTable.Columns.Add("PatientID", System.Type.GetType("System.String"));
            _observationDataTable.Columns.Add("VisitID", System.Type.GetType("System.String"));
            _observationDataTable.Columns.Add("VisitID2", System.Type.GetType("System.String"));
            _observationDataTable.Columns.Add("PatientName", System.Type.GetType("System.String"));
            _observationDataTable.Columns.Add("OccurTime", System.Type.GetType("System.String"));
            _observationDataTable.Columns.Add("Type", System.Type.GetType("System.String"));
            _observationDataTable.Columns.Add("Name", System.Type.GetType("System.String"));
            _observationDataTable.Columns.Add("Result", System.Type.GetType("System.String"));
            _observationDataTable.Columns.Add("Unit", System.Type.GetType("System.String"));
            _observationDataTable.Columns.Add("Abnormal", System.Type.GetType("System.String"));

            _medicalInterventionDataTable = new System.Data.DataTable("MedicalIntervention");
            _medicalInterventionDataTable.Columns.Add("PatientID", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("VisitID", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("VisitID2", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("PatientName", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("OccurTime", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("Type", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("Name", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("StartTime", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("EndTime", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("Amount", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("Unit", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("Frequency", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("Duration", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("OrderBy", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("PerformBy", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("Parameter", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("Description", System.Type.GetType("System.String"));
            _medicalInterventionDataTable.Columns.Add("Impression", System.Type.GetType("System.String"));
        }

        public void LoadEncodingDictionary(string encodingDictionaryPath)
        {
            try
            {
                _encodingDictionaryXml = new XmlDocument();
                _encodingDictionary = new Dictionary<string, string>();
                _encodingDictionaryXml.Load(encodingDictionaryPath);
                _encodingDictionaryFilePath = encodingDictionaryPath;
                XmlNodeList words = _encodingDictionaryXml.SelectNodes("//Word");
                foreach (XmlNode word in words)
                {
                    _encodingDictionary.Add(word.Attributes["Encoding"].Value, word.Attributes["Name"].Value);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Loading Encoding Dictionary " + encodingDictionaryPath + " failed. Error message: " + ex.Message, ex);
            }

        }

        public void LoadEventLog(string eventLogPath)
        {
            try
            {
                _eventLogXml = new XmlDocument();
                _eventLogXml.Load(eventLogPath);
                _eventLogFilePath = eventLogPath;
                _isEncoded = (_eventLogXml.SelectSingleNode(".//EventLog").Attributes["Encoding"].Value.Equals("Yes"));
                if (_isEncoded)
                {
                    System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();
                    openFileDialog.Filter = "XML|*.xml";
                    openFileDialog.Title = "Encoding Dictionary";
                    if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        LoadEncodingDictionary(openFileDialog.FileName);
                    }
                    else
                    {
                        //
                    }
                }
                _patientNodes = _eventLogXml.SelectNodes("//PatientTrace");
                foreach (XmlNode patientNode in _patientNodes)
                {
                    LoadPatientNode(patientNode);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Loading Event Log " + eventLogPath + " failed. Error message: " + ex.Message, ex);
            }
        }

        private void LoadPatientNode(XmlNode patientNode)
        {
            string patientID = "";
            string visitID = "";
            string visitID2 = "";
            string patientName = "";
            if (patientNode.Attributes["PatientID"] != null)
            {
                patientID = patientNode.Attributes["PatientID"].Value;
            }
            if (patientNode.Attributes["VisitID"] != null)
            {
                visitID = patientNode.Attributes["VisitID"].Value;
            }
            if (patientNode.Attributes["VisitID2"] != null)
            {
                visitID2 = patientNode.Attributes["VisitID2"].Value;
            }
            if (patientNode.Attributes["PatientName"] != null)
            {
                patientName = patientNode.Attributes["PatientName"].Value;
            }
            XmlNodeList observations = patientNode.SelectNodes(".//Observation");
            foreach (XmlNode observationNode in observations)
            {
                LoadObservationNode(patientID, visitID, visitID2, patientName, observationNode);
            }
            XmlNodeList medicalInterventions = patientNode.SelectNodes(".//MedicalIntervention");
            foreach (XmlNode medicalInterventionNode in medicalInterventions)
            {
                LoadMedicalInterventionNode(patientID, visitID, visitID2, patientName, medicalInterventionNode);
            }
        }

        private void LoadObservationNode(string patientID, string visitID, string visitID2, string patientName, XmlNode observationNode)
        {
            DataRow dr = _observationDataTable.NewRow();
            dr["PatientID"] = patientID;
            dr["VisitID"] = visitID;
            dr["VisitID2"] = visitID2;
            dr["PatientName"] = patientName;
            string time = RemoveTZ(observationNode.Attributes["OccurTime"].Value.ToString());
            dr["OccurTime"] = time;
            dr["Type"] = observationNode.Attributes["Type"].Value.ToString();
            foreach (XmlNode node in observationNode.ChildNodes)
            {
                switch (node.Name)
                {
                    case "Name":
                        {
                            string word;
                            if (_isEncoded)
                            {
                                if (_encodingDictionary.TryGetValue(node.InnerText, out word))
                                {
                                    dr["Name"] = word;
                                }
                                else
                                {
                                    dr["Name"] = node.InnerText;
                                }
                            }
                            else
                            {
                                dr["Name"] = node.InnerText;
                            }
                            break;
                        }
                    case "Result":
                        {
                            dr["Result"] = node.InnerText;
                            if (node.Attributes.Count != 0)
                            {
                                dr["Unit"] = node.Attributes["Unit"].Value.ToString();
                            }
                            break;
                        }
                    case "Abnormal":
                        {
                            dr["Abnormal"] = node.InnerText;
                            break;
                        }

                }
            }
            _observationDataTable.Rows.Add(dr);
        }

        private void LoadMedicalInterventionNode(string patientID, string visitID, string visitID2, string patientName, XmlNode medicalInterventionNode)
        {
            DataRow dr = _medicalInterventionDataTable.NewRow();
            dr["PatientID"] = patientID;
            dr["VisitID"] = visitID;
            dr["VisitID2"] = visitID2;
            dr["PatientName"] = patientName;
            string time = RemoveTZ(medicalInterventionNode.Attributes["OccurTime"].Value.ToString());
            dr["OccurTime"] = time;
            dr["Type"] = medicalInterventionNode.Attributes["Type"].Value.ToString();
            foreach (XmlNode node in medicalInterventionNode.ChildNodes)
            {
                switch (node.Name)
                {
                    case "Name":
                        {
                            string word;
                            if (_isEncoded)
                            {
                                if (_encodingDictionary.TryGetValue(node.InnerText, out word))
                                {
                                    dr["Name"] = word;
                                }
                                else
                                {
                                    dr["Name"] = node.InnerText;
                                }
                            }
                            else
                            {
                                dr["Name"] = node.InnerText;
                            }
                            break;
                        }
                    case "Result":
                        {
                            foreach (XmlNode node11 in node.ChildNodes)
                            {
                                if (node11.Name.Equals("Numberic"))
                                {
                                    dr["Parameter"] = node11.InnerText;
                                }
                                if (node11.Name.Equals("Literal"))
                                {

                                    if (node11.Attributes[0].Value.ToString().Equals("Description"))
                                    {
                                        dr["Description"] = node11.InnerText;
                                    }
                                    if (node11.Attributes[0].Value.ToString().Equals("Impression"))
                                    {
                                        dr["Impression"] = node11.InnerText;
                                    }
                                }
                            }
                            break;
                        }
                    case "StartTime":
                        {
                            dr["StartTime"] = RemoveTZ(node.InnerText);
                            break;
                        }
                    case "EndTime":
                        {
                            dr["EndTime"] = RemoveTZ(node.InnerText);
                            break;
                        }
                    case "Amount":
                        {
                            dr["Amount"] = node.InnerText;
                            if (node.Attributes.Count != 0)
                            {
                                dr["Unit"] = node.Attributes["Unit"].Value.ToString();
                            }
                            break;
                        }
                    case "Frequency":
                        {
                            dr["Frequency"] = node.InnerText;
                            if (node.Attributes.Count != 0)
                            {
                                dr["Duration"] = node.Attributes["Duration"].Value.ToString();
                            }
                            break;
                        }
                    case "OrderBy":
                        {
                            dr["OrderBy"] = node.InnerText;
                            break;
                        }
                    case "PerformBy":
                        {
                            dr["PerformBy"] = node.InnerText;
                            break;
                        }
                }
            }
            _medicalInterventionDataTable.Rows.Add(dr);

        }


        private string RemoveTZ(string str)
        {
            str = str.Replace("T", " ");
            str = str.Replace("Z", "");
            return str;
        }
    }



}
